package log

import (
	"fmt"
	"os"
	"time"

	logEnum "core/enum/log"
	"core/model/config"
	"core/model/config/log"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

type base struct {
	logger *zap.Logger
}

func (b base) Debug(msg string, fields ...interface{}) {
	var zapFields []zapcore.Field
	for _, v := range fields {
		zapFields = append(zapFields, v.(zapcore.Field))
	}

	b.logger.Debug(msg, zapFields...)
}

func (b base) Error(msg string, fields ...interface{}) {
	var zapFields []zapcore.Field
	for _, v := range fields {
		zapFields = append(zapFields, v.(zapcore.Field))
	}

	b.logger.Error(msg, zapFields...)
}

func (b base) Info(msg string, fields ...interface{}) {
	var zapFields []zapcore.Field
	for _, v := range fields {
		zapFields = append(zapFields, v.(zapcore.Field))
	}

	b.logger.Info(msg, zapFields...)
}

func (b base) Panic(msg string, fields ...interface{}) {
	var zapFields []zapcore.Field
	for _, v := range fields {
		zapFields = append(zapFields, v.(zapcore.Field))
	}

	b.logger.Panic(msg, zapFields...)
}

func (b base) Warn(msg string, fields ...interface{}) {
	var zapFields []zapcore.Field
	for _, v := range fields {
		zapFields = append(zapFields, v.(zapcore.Field))
	}

	b.logger.Warn(msg, zapFields...)
}

func newLogger(config *config.Config, t logEnum.Value, levels map[zapcore.Level]string) (*zap.Logger, error) {
	var rootDir string
	var maxSize, maxBackups, maxAge int
	var compress bool

	var conf log.LogConfig
	switch t {
	case logEnum.SeverLog:
		conf = config.Log.Server
	case logEnum.CronLog:
		conf = config.Log.Cron
	default:
		panic(fmt.Sprintf("无效log类型:%v", t))
	}

	rootDir = conf.RootDir
	maxSize = conf.MaxSize
	maxBackups = conf.MaxBackups
	maxAge = conf.MaxAge
	compress = conf.Compress

	// 判断目录是否存在
	_, err := os.Stat(rootDir)
	if os.IsNotExist(err) {
		// 创建根目录
		if err = os.MkdirAll(rootDir, os.ModePerm); err != nil {
			return nil, err
		}
	}

	// 扩展Zap
	var encoder zapcore.Encoder

	// 调整编码器默认配置
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = func(time time.Time, encoder zapcore.PrimitiveArrayEncoder) {
		encoder.AppendString(time.Format("[" + "2006-01-02 15:04:05.000" + "]"))
	}
	encoderConfig.EncodeLevel = func(l zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) {
		encoder.AppendString(string(config.Server.Env) + "." + l.String())
	}

	// 设置编码器
	encoder = zapcore.NewJSONEncoder(encoderConfig)

	var cores []zapcore.Core
	for level, suffix := range levels {
		cores = append(cores, zapcore.NewCore(
			encoder,
			zapcore.AddSync(&lumberjack.Logger{
				Filename:   rootDir + "/" + config.Server.Name + "_" + suffix + ".log",
				MaxSize:    maxSize,
				MaxBackups: maxBackups,
				MaxAge:     maxAge,
				Compress:   compress,
			}),
			zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
				return lvl == level
			}),
		))
	}

	return zap.New(zapcore.NewTee(cores...), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel)), nil
}
